﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Text;

namespace CoreShop.App.Units.Interface
{
    public class AbcpInvoke
    {
        // private static string FromUtf8string(string utf8)
        // {
        //     byte[] buff = System.Text.Encoding.Default.GetBytes(utf8);
        //     return System.Text.Encoding.UTF8.Getstring(buff);
        // }
        // private static string FromUtf8stringPtr(IntPtr data)
        // {
        //     string utf8 = Marshal.PtrTostringAnsi(data);
        //     return FromUtf8string(utf8);
        // }
        public delegate void CallbackString(string result);
        public delegate void CallbackResponse(int code,string subCode,string subMsg,string result);

        private static int msSeedId = 256;
        private static Object msLockObj = new Object();
        private static Dictionary<int, CallbackString> msMapAbcpString    = new Dictionary<int, CallbackString>();

        struct ABCPCallback {
            public CallbackResponse process;
            public CallbackResponse finish;
        };
        private static Dictionary<int, ABCPCallback> msMapAbcpCallback = new Dictionary<int, ABCPCallback>();
        private static AbcpNative msAbcpNative = new AbcpNative();
        /////////////////////

        private static AbcpNative.CallbackAbcpResponse msOnNativeProcess = new AbcpNative.CallbackAbcpResponse(AbcpInvoke.OnAbcpProcess);
        private static AbcpNative.CallbackAbcpResponse msOnNativeFinish = new AbcpNative.CallbackAbcpResponse(AbcpInvoke.OnAbcpFinish);
        private static AbcpNative.CallbackAbcpString msOnNativeAbcpstring = new AbcpNative.CallbackAbcpString(AbcpInvoke.OnAbcpString);

        public static void OnAbcpString(int seedId, string result)
        {
            CallbackString callback = null;

            lock(msLockObj)
            {
                if (msMapAbcpString.ContainsKey(seedId)) {
                    callback = msMapAbcpString[seedId];
                    msMapAbcpString.Remove(seedId);
                }
            }
            if (callback != null) {
                callback(result);
            }
        }

        public static void AbcpZimIdInitTest(string metainfo, string smileType, string smileFlag, CallbackString callback)
        {
            int seedId = 0;
            lock (msLockObj)
            {
                seedId = msSeedId++;
                msMapAbcpString[seedId] = callback;
            }
            msAbcpNative.ZimIdInitTest(seedId, metainfo, smileType, smileFlag, msOnNativeAbcpstring);
        }

        /////////////////////
        
        public static void OnAbcpProcess(int seedId, int code,
            [MarshalAs(UnmanagedType.LPStr)] string subCode, 
            [MarshalAs(UnmanagedType.LPStr)] string subMsg,
            [MarshalAs(UnmanagedType.LPStr)] string result)
        {
            ABCPCallback callback;
            callback.process = null;
            lock (msLockObj)
            {
                if (msMapAbcpCallback.ContainsKey(seedId))
                {
                    callback = msMapAbcpCallback[seedId];
                }
            }

            if (callback.process != null)
            {
                callback.process(code, subCode, subMsg, result);
            }
        }
        public static void OnAbcpFinish(int seedId, int code,
            [MarshalAs(UnmanagedType.LPStr)] string subCode, 
            [MarshalAs(UnmanagedType.LPStr)] string subMsg,
            [MarshalAs(UnmanagedType.LPStr)] string result)
        {
            ABCPCallback callback;
            callback.finish = null;
            lock (msLockObj)
            {
                if (msMapAbcpCallback.ContainsKey(seedId))
                {
                    callback = msMapAbcpCallback[seedId];
                    msMapAbcpCallback.Remove(seedId);
                }
            }

            if (callback.finish != null)
            {
                callback.finish(code, subCode, subMsg, result);
            }
        }

        public static void SetAPIPathFile(string file)
        {
            msAbcpNative.InitAPIDylib(file);
        }
        public static void AbcpInit(string appId, string appVersion, string json, CallbackResponse process, CallbackResponse finish)
        {
            int seedId = 0;
            ABCPCallback callback;
            callback.process = process;
            callback.finish  = finish;
            lock (msLockObj)
            {
                seedId = msSeedId++;
                msMapAbcpCallback[seedId] = callback;
            }

            msAbcpNative.BPCallInit(seedId, appId, appVersion, json, msOnNativeProcess, msOnNativeFinish);
        }
        public static void AbcpGetMetaInfo(string appId, string json, CallbackResponse process, CallbackResponse finish)
        {
            int seedId = 0;
            ABCPCallback callback;
            callback.process = process;
            callback.finish = finish;
            lock (msLockObj)
            {
                seedId = msSeedId++;
                msMapAbcpCallback[seedId] = callback;
            }

            msAbcpNative.BPGetMetaInfo(seedId, appId, json, msOnNativeProcess, msOnNativeFinish);
        }
        public static void AbcpStartService(string appId, string serviceCode, string json, CallbackResponse process, CallbackResponse finish)
        {
            int seedId = 0;
            ABCPCallback callback;
            callback.process = process;
            callback.finish = finish;
            lock (msLockObj)
            {
                seedId = msSeedId++;
                msMapAbcpCallback[seedId] = callback;
            }

            msAbcpNative.BPStartService(seedId, appId, serviceCode, json, msOnNativeProcess, msOnNativeFinish);
        }
        public static void AbcpStopService(string appId, string serviceCode, string json, CallbackResponse process, CallbackResponse finish)
        {
            int seedId = 0;
            ABCPCallback callback;
            callback.process = process;
            callback.finish = finish;
            lock (msLockObj)
            {
                seedId = msSeedId++;
                msMapAbcpCallback[seedId] = callback;
            }

            msAbcpNative.BPStopService(seedId, appId, serviceCode, json, msOnNativeProcess, msOnNativeFinish);
        }
        public static void AbcpSubscribeEvent(string appId, string json, CallbackResponse process, CallbackResponse finish)
        {
            int seedId = 0;
            ABCPCallback callback;
            callback.process = process;
            callback.finish = finish;
            lock (msLockObj)
            {
                seedId = msSeedId++;
                msMapAbcpCallback[seedId] = callback;
            }

            msAbcpNative.BPSubscribeEvent(seedId, appId, json, msOnNativeProcess, msOnNativeFinish);
        }
        public static void AbcpUnsubscribeEvent(string appId, string json, CallbackResponse process, CallbackResponse finish)
        {
            int seedId = 0;
            ABCPCallback callback;
            callback.process = process;
            callback.finish = finish;
            lock (msLockObj)
            {
                seedId = msSeedId++;
                msMapAbcpCallback[seedId] = callback;
            }

            msAbcpNative.BPUnsubscribeEvent(seedId, appId, json, msOnNativeProcess, msOnNativeFinish);
        }
    }
}
